package com.android.love.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

import com.android.love.BuildConfig;

/**
 * 缓存工具类
 * 
 * @author adison
 * 
 */
public class CacheUtils {

    public final static String TAG="cache";

    private CacheUtils() {
    };

    /** 缓存大小 **/
    public static final int HTTP_CACHE_SIZE=10 * 1024 * 1024; // 10MB

    /** 缓存目录 **/
    public static final String HTTP_CACHE_DIR="http";

    /** 默认缓存大小 **/
    public static final int DEFAULT_CACHE_FILE_SIZE=10 * 512; // 512 kb

    /** 默认缓存图片目录 **/
    public static final String IMAGE_CACHE_DIR="thumbs";

    public static final String IMAGE_CACHE_PIC_DIR="pics";

    /** 8K缓存 **/
    public static final int IO_BUFFER_SIZE=8 * 1024;

    public static File cacheDir;

    /**
     * 检查提供的路径有多少可用的空间
     * 
     * @param path
     * @return
     */
    @SuppressLint("NewApi")
    // TODO: Parameter 'path' is not assigned and could be declared final
    public static long getUsableSpace(File path) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            Debug("2.3->" + path.getUsableSpace());
            return path.getUsableSpace();
        }
        // Debug("2.1->" + path.getUsableSpace());
        final StatFs stats=new StatFs(path.getPath());
        return (long)stats.getBlockSize() * (long)stats.getAvailableBlocks();
    }

    /**
     * Check if external storage is built-in or removable. 2.3 以后的手机可以区分
     * 内部大容量存储器 和 外部 内部为不可移除这样更保证我们程序缓存的稳定性
     * 
     * 注意! 2.3 以前没这个特性...蛋疼..
     * 
     * @return True if external storage is removable (like an SD card), false
     *         otherwise.
     */
    @SuppressLint("NewApi")
    public static boolean isExternalStorageRemovable() {
        // 2.3 以后才支持的参数
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            return Environment.isExternalStorageRemovable();
        }
        // 返回false 强制使用外部存储器
        return false;
    }

    /**
     * 检查是否支持外部cachedir 目录
     * 
     * @return
     */
    public static boolean hasExternalCacheDir() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
    }

    /**
     * 获得程序在sd卡上的cahce目录
     * 
     * @param context
     *            The context to use
     * @return The external cache dir
     */
    @SuppressLint("NewApi")
    public static File getExternalCacheDir(Context context) {

        File appCacheDir=null;
        // android 2.2 以后才支持的特性
        if(hasExternalCacheDir() && (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))) {
            final String cacheDir="/abuse/record/app/";
            appCacheDir=new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
            if(!appCacheDir.exists()) {
                appCacheDir.mkdirs();
            }
            // appCacheDir =
            // Environment.getExternalStorageDirectory()+"/record/app/";
        }
        // else if (Environment.getExternalStorageState().equals(
        // android.os.Environment.MEDIA_MOUNTED)) {
        //
        // // Before Froyo we need to construct the external cache dir
        // // ourselves
        // // 2.2以前我们需要自己构造

        // }
        if(appCacheDir == null) {
            appCacheDir=context.getCacheDir();
        }

        return appCacheDir;
    }

    /**
     * 获取用户缓存目录
     * 
     * @param context
     * @return
     */
    public static File getUserCache(Context context, String cacheDir) {
        File appCacheDir=null;
        // android 2.2 以后才支持的特性
        if(hasExternalCacheDir() && (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))) {
            // final String cacheDir="/culiu_alarm/record/";
            // final String cacheDir = "/my/";
            appCacheDir=new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
            if(!appCacheDir.exists()) {
                appCacheDir.mkdirs();
            }
            // appCacheDir =
            // Environment.getExternalStorageDirectory()+"/record/app/";
        }
        if(appCacheDir == null) {
            appCacheDir=context.getCacheDir();
        }

        return appCacheDir;
    }

    /**
     * Check if OS version has a http URLConnection bug. See here for more
     * information:
     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
     * 检查系统版本是否有URLConnection的bug
     * 
     * @return
     */
    public static boolean hasHttpConnectionBug() {
        return Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR;
    }

    /**
     * Workaround for bug pre-Froyo, see here for more info:
     * http://android-developers.blogspot.com/2011/09/androids-http-clients.html
     * 2.1 以前的版本你需要手动设置!
     */
    public static void disableConnectionReuseIfNecessary() {
        // HTTP connection reuse which was buggy pre-froyo
        if(hasHttpConnectionBug()) {
            System.setProperty("http.keepAlive", "false");
        }
    }

    // /**
    // * 根据url生成缓存文件完整路径名
    // *
    // * @param url
    // * @return
    // */
    // public static String urlToFilePath(Context context, String url) {
    // cacheDir = DiskLruCache.getDiskCacheDir(context,
    // CacheUtils.IMAGE_CACHE_DIR);
    // return DiskLruCache.createFilePath(cacheDir, url);
    // }

    /**
     * 复制流
     * 
     * @param in
     * @param out
     */
    public static void CopyStream(InputStream in, OutputStream out) {
        final int buffer_size=1024;
        try {
            byte[] bytes=new byte[buffer_size];
            for(;;) {
                int count=in.read(bytes, 0, buffer_size);
                if(count == -1)
                    break;
                out.write(bytes, 0, count);
            }
        } catch(Exception ex) {
        }

        // 实现二
        // int b;
        // while ((b = in.read()) != -1) {
        // out.write(b);
        // }

    }

    /**
     * 复制文件
     * 
     * @param sourceFile
     * @param targetFile
     * @throws IOException
     */
    public static void copyFile(File sourceFile, File targetFile) throws IOException {
        BufferedInputStream inBuff=null;
        BufferedOutputStream outBuff=null;
        try {
            inBuff=new BufferedInputStream(new FileInputStream(sourceFile));

            outBuff=new BufferedOutputStream(new FileOutputStream(targetFile));
            // 缓冲数组
            // TODO: Local variable could be declared final
            byte[] b=new byte[1024 * 5];
            int len;
            // TODO: Avoid assigments in operands
            while((len=inBuff.read(b)) != -1) {
                outBuff.write(b, 0, len);
            }
            // 刷新此缓冲的输出流
            outBuff.flush();
        } finally {
            // 关闭流
            if(inBuff != null)
                inBuff.close();
            if(outBuff != null)
                outBuff.close();
        }
    }

    /**
     * 获取到android分给每一个进程的最大可以用的内存，这些内存是native heap + java heap
     * 
     * @param context
     * @return
     */
    // TODO: Parameter 'context' is not assigned and could be declared final
    @SuppressLint("NewApi")
    public static int getMemoryClass(Context context) {
        return ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
    }

    // TODO: Parameter 'message' is not assigned and could be declared final
    public static void Debug(String message) {
        if(BuildConfig.DEBUG) {
            Log.d(TAG, message);
        }
    }

}
